/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.gen;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.android.dx.rop.code.BasicBlock;
import com.android.dx.rop.code.Insn;
import com.android.dx.rop.code.InsnList;
import com.android.dx.util.IntList;

/**
 * A branch target in a list of instructions.
 */
public final class Label {

	final List<Insn> instructions = new ArrayList<Insn>();

	boolean marked = false;

	/** an immutable list of labels corresponding to the types in the catch list */
	List<Label> catchLabels = Collections.emptyList();

	/** contains the next instruction if no branch occurs */
	Label primarySuccessor;

	/** contains the instruction to jump to if the if is true */
	Label alternateSuccessor;

	int id = -1;

	Label() {
	}

	boolean isEmpty() {
		return instructions.isEmpty();
	}

	void compact() {
		for (int i = 0; i < catchLabels.size(); i++) {
			while (catchLabels.get(i).isEmpty()) {
				catchLabels.set(i, catchLabels.get(i).primarySuccessor);
			}
		}
		while (primarySuccessor != null && primarySuccessor.isEmpty()) {
			primarySuccessor = primarySuccessor.primarySuccessor;
		}
		while (alternateSuccessor != null && alternateSuccessor.isEmpty()) {
			alternateSuccessor = alternateSuccessor.primarySuccessor;
		}
	}

	BasicBlock toBasicBlock() {
		InsnList result = new InsnList(instructions.size());
		for (int i = 0; i < instructions.size(); i++) {
			result.set(i, instructions.get(i));
		}
		result.setImmutable();

		int primarySuccessorIndex = -1;
		IntList successors = new IntList();
		for (Label catchLabel : catchLabels) {
			successors.add(catchLabel.id);
		}
		if (primarySuccessor != null) {
			primarySuccessorIndex = primarySuccessor.id;
			successors.add(primarySuccessorIndex);
		}
		if (alternateSuccessor != null) {
			successors.add(alternateSuccessor.id);
		}
		successors.setImmutable();

		return new BasicBlock(id, result, successors, primarySuccessorIndex);
	}
}
